import json,cv2,base64
import numpy as np
import flask,svgwrite,optparse
from io import BytesIO
from PIL import Image
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch,ArrowStyle
import tornado.wsgi
import tornado.httpserver
import sys,time,codecs
from wand.image import Image as wandImage
from fix_tex import fix_tex_site
from common import log_init
# print("sys.stdout.encodeing:", sys.stdout.encoding)
#设置py文件的编码格式为utf-8
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())



def remote_call(url, pic_name):
    # ---------------------------------->v2.0
    #pic_name  is array
    pic=cv2.imencode(".jpg",pic_name)[1].tostring() #tostring
    pic=base64.b64encode(pic)
    registered_data={"Pic":pic.decode()} #to key-val
    data=json.dumps(registered_data) # 将一个Python数据结构转换为JSON
    import requests
    r=requests.post(url,data)  #
    # ---------------------------------->v1.0
    # f_register = open(pic_name, 'rb')
    # b64_register = base64.b64encode(f_register.read())
    # register_data = {"Pic": b64_register.decode()}
    # data = json.dumps(register_data)
    # import requests
    # r=requests.post(url, data)

    return json.loads(r.content)["results"]

#----------------------draw_lines_arrow-------------------------------
def draw_lines(lines, ax,offset):
    #line
    for x0, y0, x1, y1, score in lines[0]:
        # ax.plot([x0, x1], [y0, y1],color='black',linewidth = '1.5')
        # line=ax.line((x0+offset, y0), (x1+offset, y1))
        # ax.add(line)
        polyline = ax.polyline(points=[(x0+offset, y0), (x1+offset,y1)], fill='none', stroke='#000',stroke_width=1)
        ax.add(polyline)

    #arrow
    for x0, y0, x1, y1, score in lines[1]:
        arrow = create_arrow_marker(ax)
        arrow_line = ax.line(start=(x0 + offset, y0), end=(x1 + offset, y1), stroke='#000000', stroke_width=1,
                       marker_end=arrow.get_funciri())
        ax.add(arrow_line)

    #solid_point
    for points in lines[2]:

        marker_start = ax.marker(insert=(0, 0), size=(4, 4))  # target size of the marker
        marker_start.viewbox(minx=-5, miny=-5, width=10, height=10)  # the marker user coordinate space
        marker_start.add(ax.circle((0, 0), r=5)).fill('black', opacity=6)
        ax.defs.add(marker_start)
        solid_point = ax.add(ax.polyline([(points[0] + offset,points[1])], stroke='black', fill='none'))
        solid_point.set_markers((marker_start, marker_start, marker_start))

    #dashed_line
    for x0,y0,x1,y1,score in lines[3]:
        dashed_line =ax.polyline(points=[(x0+offset,y0),(x1+offset,y1)],stroke_dasharray="5,5",fill="none",stroke="#000",stroke_width=1)
        ax.add(dashed_line)


#arrow
def draw_arrow(lines, ax,offset):
    for x0, y0, x1, y1, score in lines:
        arrow = create_arrow_marker(ax)
        line = ax.line(start=(x0+offset,y0), end=(x1+offset,y1), stroke='#000000', stroke_width=1,marker_end=arrow.get_funciri())
        ax.add(line)

def create_arrow_marker(dwg):
    #   <defs>
    #     <marker id="arrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
    #       <path d="M0,0 L0,6 L9,3 z" fill="#f00" />
    #     </marker>
    #   </defs>
    arrow = dwg.marker(id='arrow', insert=(0, 3), size=(10,10), orient='auto', markerUnits='strokeWidth')
    arrow.add(dwg.path(d='M0,0 L0,6 L9,3 z', fill='#000000'))
    dwg.defs.add(arrow)
    return arrow


def draw_text(bbox, text_results, ax,offset):
    # font = matplotlib.font_manager.FontProperties(fname="fonts/simhei.ttf")
    for n, (x0, y1) in enumerate(bbox):
    #     ax.text(x0, y1, text_results[n], fontsize='xx-large', color="black", font_properties=font)
    #     print(bbox)
    #     # ax.text(x0, y1, text_results[n], fontsize='5', color="black",bbox=dict(boxstyle="square"))
    #     fontsize = int((y1-y0)/17*14)
    #     print(text_results[n])
    #     print('{} fontsize'.format(fontsize))
    #     if is_Chinese(text_results[n]):
    #         ax.text(x0, y1, text_results[n], fontsize=14,color="black",fontproperties=myfont)
    #         # ax.text(x0, y1, text_results[n], fontsize=fontsize, fontstyle='italic',color="black",fontproperties=myfont)
    #     else:
    #         ax.text(x0, y1, text_results[n], fontsize=14, fontstyle='italic', color="black")
    #         # ax.text(x0, y1, text_results[n], fontsize=fontsize, fontstyle='italic', color="black")
    # matplotlib.rcParams.update({
    # 'font.family': 'sans-serif',
    # 'font.sans-serif': ['Times New Roman'],
    # })
        if is_Chinese(text_results[n]):
            # ax.add(svgwrite.text.Text(text_results[n], insert=(x0, y1), fill='black',style="font-size:14;font-family:'Times New Roman',Times,serif;"))
            ax.add(svgwrite.text.Text(text_results[n], insert=(x0+offset, y1),style="font-size:14"))
        else:
            # ax.add(svgwrite.text.Text(text_results[n], insert=(x0, y1), fill='black',style="font-size:14;font-style: italic;font-family:'Times New Roman',Times,serif;"))
            ax.add(svgwrite.text.Text(text_results[n], insert=(x0+offset, y1), class_="xt",style="font-size:14"))
    pass



def is_Chinese(word):
    for ch in word:
        if '\u4e00' <= ch <= '\u9fff':
            return True
    return False


def insert_pic(dwg):
    # Load PNG Image
    # dwg = svgwrite.Drawing()
    img = wandImage(filename="query.jpg")
    # Then get raw PNG data and encode DIRECTLY into the SVG file.
    image_data = img.make_blob(format='png')
    encoded = base64.b64encode(image_data).decode()
    pngdata = 'data:image/png;base64,{}'.format(encoded)

    image = dwg.add(dwg.image(href=(pngdata),insert=(0,0)))
    return  image



# Obtain the flask app object
app = flask.Flask(__name__)
@app.route('/recog', methods=['POST'])
def registered_user():
    print('wo')
    try:
        #The file is dict,the pic is binary.
        get_file = flask.request.files['file']
        pic = get_file.read()
        # user_image = Image.open(StringIO(pic))
        user_image = Image.open(BytesIO(pic))
        user_image = np.asarray(user_image)
        img = user_image
        local_time = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime())
        path = rf"./pic/{local_time}.png"
        cv2.imwrite('query.jpg',img)

        recog(img)

        with open('output/query.svg','rb') as f:
            content = f.readlines()
        style = """ <style type="text/css">
        <![CDATA[
        line{ stroke:black;stroke-width:1 }
        circle{opacity:0;stroke:black}
        text{ font-size:14;font-family:"Times New Roman",SimSun,"Microsoft YaHei";fill:black }
        .xt{ font-style:italic }]]></style><defs />'
        """
        a = content[0].decode()+content[1].decode().replace('<defs />',style)
        return a
    except Exception as e:
        import logging
        logging.exception(e)
        return 'error'


def recog(image):
    dwg = svgwrite.Drawing("./output/query.svg")
    line_url = 'http://localhost:28600/detect_lines'
    text_rcog_url = 'http://localhost:28601/recog_text'
    lines_results = remote_call(line_url, image)
    text_result = remote_call(text_rcog_url, image)


    draw_lines(lines_results, dwg, image.shape[1])
    text_recog_results = [text_result]
    text_bboxes_processed=[[5,10,47,19]]
    temp_box = fix_tex_site(text_bboxes_processed, lines_results[0]+lines_results[1], 8)
    draw_text(temp_box, text_recog_results, dwg,image.shape[1])

    # plt.tight_layout()
    insert_pic(dwg)  #close origin_image
    dwg.save()
    # plt.show()



def start_from_terminal(app):
    parser = optparse.OptionParser()
    parser.add_option(
        '-p', '--port',
        help="which port to serve content on",
        type='int', default=8096)
    parser.add_option(
        '-g', '--gpu',
        help="use gpu mode",
        action='store_false', default=True)

    opts, args = parser.parse_args()

    #app.run(port= opts.port)
    http_server = tornado.httpserver.HTTPServer(
        tornado.wsgi.WSGIContainer(app))
    http_server.listen(opts.port, address="0.0.0.0")
    tornado.ioloop.IOLoop.instance().start()
    # start_tornado(app, opts.port)

if __name__ == '__main__':
    log_init(r"./log/app_log.txt")
    start_from_terminal(app)

